using System;
using System.Collections.Generic;
using System.Text;

namespace Lib.Extraction
{
    public class Extracting
    {
        string splitter = "";
        string[] FieldList;
        string _siteName = "";
        System.Collections.Queue st = new System.Collections.Queue();
        System.Collections.Queue fst = new System.Collections.Queue();

        int _total = 0;
        //int _queue = 0;
        int _processed = 0;

        public int Total { get { return _total; } }
        public int InQueu { get { return fst.Count; } }
        public int Processed { get { return _processed; } }
        
        public void ProcessDataFiles(string Separator, string siteName, string[] ListField)
        {
            System.Threading.ThreadPool.SetMaxThreads(10, 20);
            FieldList = ListField;
            splitter = Separator;
            _siteName = siteName;
            string[] FileName = Utilities.FileUtility.GetListFileNames(AppDomain.CurrentDomain.BaseDirectory + "\\Files\\RAW\\" + _siteName + "\\",true).Split(',');
            _total = FileName.Length;
            foreach (string f in FileName)
            {
                if (!string.IsNullOrEmpty(f))
                {
                    fst.Enqueue(f);
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ProcessFileData), Separator);
                }
                else
                    _total--;
                    
            }
        }

        void ProcessFileData(object obj)
        {
            if (fst.Count > 0)
            {
                string FileName = (string)fst.Dequeue();
                if (!string.IsNullOrEmpty(FileName))
                {
                    //st.Enqueue(Utilities.FileUtility.GetFileContent(FileName, true));
                    string Content = Utilities.FileUtility.GetFileContent(FileName, false);
                    if (!string.IsNullOrEmpty(Content) && FieldList.Length > 0)
                    {

                        //Get URL Information if there're
                        string URL = "";
                        string URLName = "";
                        string[] URLContent = Content.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                        if (URLContent.Length > 0)
                        {
                            URL = URLContent[0];

                            if (URL.ToLower().IndexOf("http://") >= 0)
                            {
                                Content = Content.Remove(0, Content.IndexOf(Environment.NewLine));
                                if (URLContent.Length > 1)
                                {
                                    URLName = URLContent[1];
                                    Content = Content.Remove(0, Content.IndexOf(Environment.NewLine));
                                }
                            }
                            else
                                URL = "";
                            if (string.IsNullOrEmpty(URLName))
                                URLName = URL;
                        }
                        URLContent = null;

                        string[] contentArr = Content.Split(new string[] { splitter }, StringSplitOptions.RemoveEmptyEntries);
                        string[] valueArr = new string[FieldList.Length];

                        if (FieldList.Length > 0 && contentArr.Length > 0)
                        {
                            while (contentArr.Length > 0)
                            {
                                if (Array.IndexOf(contentArr, FieldList[0]) < 0)
                                    break;
                                int minIndex = Array.IndexOf(contentArr, FieldList[0]);
                                int firstIndex = Array.IndexOf(contentArr, FieldList[0]);
                                for (int i = 1; i < FieldList.Length; i++)
                                {
                                    int curIndex = Array.IndexOf(contentArr, FieldList[i].Trim());
                                    if (curIndex < minIndex)
                                        minIndex = curIndex;
                                    if (Math.Abs(firstIndex - curIndex) <= 4)
                                    {
                                        System.Collections.Queue fieldIndexes = new System.Collections.Queue();
                                        for (int j = 0; j < FieldList.Length; j++)
                                        {
                                            int ind = Array.IndexOf(contentArr, FieldList[j]);
                                            if (ind >= 0)
                                                fieldIndexes.Enqueue(ind);
                                        }
                                        int[] fArr = new int[fieldIndexes.Count];
                                        fieldIndexes.CopyTo(fArr, 0);
                                        Array.Sort(fArr);

                                        string[] fieldNames = new string[fArr.Length];
                                        string[] fieldValues = new string[fArr.Length];
                                        int count = 0;
                                        for (int k = 0; k < fArr.Length; k++)
                                        {
                                            if (k == 0 && k < fArr.Length - 1 && fArr[k + 1] - fArr[k] > 4)
                                                break;
                                            if (k > 0 && k < fArr.Length - 1 && (fArr[k + 1] - fArr[k] > 4 || fArr[k] - fArr[k - 1] > 4))
                                                break;
                                            if (k > 0 && k == fArr.Length - 1 && fArr[k] - fArr[k - 1] > 4)
                                                break;
                                            fieldNames[count] = contentArr[fArr[k]];
                                            fieldValues[count] = contentArr[fArr[k] + 1];
                                            count++;
                                        }
                                        if (count > 0)
                                        {
                                            string[] NamesResult = new string[count];
                                            string[] ValuesResult = new string[count];
                                            Array.Copy(fieldNames, 0, NamesResult, 0, count);
                                            Array.Copy(fieldValues, 0, ValuesResult, 0, count);
                                            Utilities.FileUtility.SaveDataToRandomFile((string.IsNullOrEmpty(URL) ? "" : "URL*/*URL Name*/*") + string.Join("*/*", NamesResult) + Environment.NewLine + (string.IsNullOrEmpty(URL) ? "" : URL + "*/*" + URLName + "*/*") + string.Join("*/*", ValuesResult), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "\\");
                                        }
                                        minIndex = fArr[fArr.Length - 1];
                                        break;
                                    }
                                }
                                string[] newArray = new string[contentArr.Length - minIndex - 1];
                                if (minIndex > 0)
                                {
                                    //contentArr.CopyTo(newArray, minIndex);
                                    //newArray.CopyTo(contentArr, minIndex);
                                    Array.Copy(contentArr, minIndex + 1, newArray, 0, contentArr.Length - minIndex - 1 - 1);
                                    contentArr = newArray;
                                }
                            }



                            // region Raw process by ordered fields
                            //for (int i = 0; i < contentArr.Length - 2; i++)
                            //{
                            //if (contentArr[i].IndexOf(FieldList[0]) >= 0 && contentArr[i + 2].IndexOf(FieldList[1]) >= 0)
                            //{
                            //    for (int j = 0; j < FieldList.Length; j++)
                            //    {
                            //        valueArr[j] = contentArr[i + j * 2 + 1];
                            //    }
                            //    Utilities.FileUtility.SaveDataToRandomFile(string.Join("*/*", FieldList) + Environment.NewLine + string.Join("*/*", valueArr), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "\\");
                            //    //Utilities.FileUtility.SaveDataToFile(string.Join("/", valueArr), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "");
                            //    break;
                            //}
                            //}

                            // end region process
                        }
                    }
                    _processed++;
                }
                else
                    _processed++;
            }
            else { _processed++; } 

        }

        void ProcessFile(object obj)
        {
            if (fst.Count > 0)
            {
                string FileName = (string)fst.Dequeue();
                if (!string.IsNullOrEmpty(FileName))
                {
                    //st.Enqueue(Utilities.FileUtility.GetFileContent(FileName, true));
                    st.Enqueue(Utilities.FileUtility.GetFileContent(FileName, false));
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ProcessData));
                }
                else
                    _processed++;
            }
        }

        void ProcessData(object obj)
        {
            //System.Threading.Thread.MemoryBarrier();
            string Content = (string)st.Dequeue();
            if (!string.IsNullOrEmpty(Content) && FieldList.Length > 0)
            {

                //Get URL Information if there're
                string URL = "";
                string URLName = "";
                string[] URLContent = Content.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                if (URLContent.Length > 0)
                {
                    URL = URLContent[0];

                    if (URL.ToLower().IndexOf("http://") >= 0)
                    {
                        Content = Content.Remove(0, Content.IndexOf(Environment.NewLine));
                        if (URLContent.Length > 1)
                        {
                            URLName = URLContent[1];
                            Content = Content.Remove(0, Content.IndexOf(Environment.NewLine));
                        }
                    }
                    else
                        URL = "";
                    if (string.IsNullOrEmpty(URLName))
                        URLName = URL;
                }
                URLContent = null;

                string[] contentArr = Content.Split(new string[] { splitter }, StringSplitOptions.RemoveEmptyEntries);
                string[] valueArr = new string[FieldList.Length];

                if (FieldList.Length > 0 && contentArr.Length > 0)
                {
                    while (contentArr.Length > 0)
                    {
                        if (Array.IndexOf(contentArr, FieldList[0]) < 0)
                            break;
                        int minIndex = Array.IndexOf(contentArr, FieldList[0]);
                        int firstIndex = Array.IndexOf(contentArr, FieldList[0]);
                        for (int i = 1; i < FieldList.Length; i++)
                        {
                            int curIndex=Array.IndexOf(contentArr, FieldList[i].Trim());
                            if (curIndex < minIndex)
                                minIndex = curIndex;
                            if (Math.Abs(firstIndex - curIndex) <= 2)
                            {
                                System.Collections.Queue fieldIndexes = new System.Collections.Queue();
                                for (int j = 0; j < FieldList.Length; j++)
                                {
                                    int ind = Array.IndexOf(contentArr, FieldList[j]);
                                    if(ind>=0)
                                    fieldIndexes.Enqueue(ind);
                                }
                                int[] fArr = new int[fieldIndexes.Count];
                                fieldIndexes.CopyTo(fArr,0);
                                Array.Sort(fArr);
                                
                                string[] fieldNames = new string[fArr.Length];
                                string[] fieldValues = new string[fArr.Length];
                                int count = 0;
                                for (int k = 0; k < fArr.Length; k++)
                                {
                                    if (k == 0 && k<fArr.Length-1 && fArr[k + 1] - fArr[k] > 2)
                                        break;
                                    if (k > 0 && k < fArr.Length-1 && (fArr[k + 1] - fArr[k] > 2 || fArr[k]-fArr[k-1]>2))
                                        break;
                                    if (k > 0 && k == fArr.Length - 1 && fArr[k] - fArr[k - 1] > 2)
                                        break;
                                    fieldNames[count] = contentArr[fArr[k]];
                                    fieldValues[count] = contentArr[fArr[k] + 1];
                                    count++;
                                }
                                if (count > 0)
                                {
                                    string[] NamesResult = new string[count];
                                    string[] ValuesResult = new string[count];
                                    Array.Copy(fieldNames, 0, NamesResult, 0, count);
                                    Array.Copy(fieldValues, 0, ValuesResult, 0, count);
                                    Utilities.FileUtility.SaveDataToRandomFile((string.IsNullOrEmpty(URL) ? "" : "URL*/*URL Name*/*") + string.Join("*/*", NamesResult) + Environment.NewLine + (string.IsNullOrEmpty(URL) ? "" : URL + "*/*" + URLName + "*/*") + string.Join("*/*", ValuesResult), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "\\");
                                }
                            }
                        }
                        string[] newArray = new string[contentArr.Length - minIndex - 1];
                        if (minIndex >= 0)
                        {
                            //contentArr.CopyTo(newArray, minIndex);
                            //newArray.CopyTo(contentArr, minIndex);
                            Array.Copy(contentArr, minIndex, newArray, 0, contentArr.Length - minIndex - 1);
                            contentArr = newArray;
                        }
                    }



                    // region Raw process by ordered fields
                    //for (int i = 0; i < contentArr.Length - 2; i++)
                    //{
                        //if (contentArr[i].IndexOf(FieldList[0]) >= 0 && contentArr[i + 2].IndexOf(FieldList[1]) >= 0)
                        //{
                        //    for (int j = 0; j < FieldList.Length; j++)
                        //    {
                        //        valueArr[j] = contentArr[i + j * 2 + 1];
                        //    }
                        //    Utilities.FileUtility.SaveDataToRandomFile(string.Join("*/*", FieldList) + Environment.NewLine + string.Join("*/*", valueArr), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "\\");
                        //    //Utilities.FileUtility.SaveDataToFile(string.Join("/", valueArr), AppDomain.CurrentDomain.BaseDirectory + "\\Files\\Processed\\" + _siteName + "");
                        //    break;
                        //}
                    //}

                    // end region process
                }
            }
            _processed++;
        }
    }
}
